package com.taotao.slink.service;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import com.taotao.slink.utils.localstore.LocalStore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.time.LocalDate;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *
 * </p>
 *
 * @author fanbeibei
 * @version 1.0.0
 * @date 2023/6/27 11:41
 */
@Slf4j
public class VisitStatistics {

    private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(20, 20, 5, TimeUnit.MINUTES,
            new ArrayBlockingQueue<>(200),new ThreadPoolExecutor.CallerRunsPolicy());


    private static final Snowflake snowflake = IdUtil.getSnowflake(RandomUtil.randomLong(32), RandomUtil.randomLong(32));


    private static ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1);


    private LocalStore localStore;

    private DayVisitService dayVisitService;


    public VisitStatistics(LocalStore localStore, DayVisitService dayVisitService) {
        this.localStore = localStore;
        this.dayVisitService = dayVisitService;
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class DayVisitInfo implements Serializable {
        private LocalDate day;
        private String code;
        private int count;
    }

    /**
     *  将访问次数保存到本地
     *
     * @param day
     * @param code
     * @param count
     */
    public void incrVisit(LocalDate day, String code, int count) {
        threadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    localStore.put(snowflake.nextIdStr(), new DayVisitInfo(day, code, count));
                } catch (Exception e) {
                    log.error("", e);
                }
            }
        });
    }


    /**
     * 将访问次数更新到数据库
     */
    private void saveVisitInfo(){
        try {
            while(true) {
                Map<String, DayVisitInfo> map = localStore.queryMap(100, DayVisitInfo.class);
                if(null == map || map.isEmpty()){
                    break;
                }

                for (Map.Entry<String, DayVisitInfo> e : map.entrySet()) {

                    // 保存到数据库
                    dayVisitService.saveVisitInfo(e.getValue());
                    localStore.delete(e.getKey());
                }
            }
        } catch (Exception e) {
            log.error("",e);
        }
    }



    public void init() throws Exception {
        localStore.start();
        scheduledExecutorService .scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                saveVisitInfo();
            }
        },5,5,TimeUnit.MINUTES);

    }
    public void shutdown(){
        threadPoolExecutor.shutdown();
        scheduledExecutorService.shutdown();

        localStore.shutdown();
    }












}
